package com.ctbri.concurrency.ex25;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.SynchronousQueue;

import com.ctbri.concurrency.LiftOff;

class LiftOffRunner implements Runnable {
	private BlockingQueue<LiftOff> rockets;
	public LiftOffRunner(BlockingQueue<LiftOff> queue){
		rockets = queue;
	}
	public void add(LiftOff lo) {
		try{
			rockets.put(lo);
		} catch(InterruptedException e) {
			System.out.println("Interrupted during put()");
		}
	}
	public void run() {
		try{
			while(!Thread.interrupted()){
				LiftOff rocket = rockets.take();
				rocket.run();
			}
		} catch(InterruptedException e) {
			System.out.println("Waking from take()");
		}
		System.out.println("Exiting LiftOffRunner");
	}
}

class LiftOffAdder implements Runnable {
	private LiftOffRunner liftOffRunner ;
	public LiftOffAdder(LiftOffRunner runner) {
		liftOffRunner = runner;
	}
	public void run() {
		for(int i = 0; i < 5; i++)
			liftOffRunner.add(new LiftOff(5));
	}
}
public class TestBlockingQueues {
	static void getkey(){
		try{
			new BufferedReader(
					new InputStreamReader(System.in)).readLine();
		} catch(IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	static void getkey(String message) {
		System.out.println(message);
		getkey();
	}
	
	static void test(String msg, BlockingQueue<LiftOff> queue) {
		System.out.println(msg);
		LiftOffRunner runner = new LiftOffRunner(queue);
		Thread t = new Thread(runner);
		t.start();
		Thread tAdd = new Thread(new LiftOffAdder(runner));
		tAdd.start();
				
		getkey("Press Enter (" + msg + ")");
		t.interrupt();
		System.out.println("Finish " + msg + " test");
	}
	
	public static void main(String[] args) {
		test("LinkedBlockingQueue", new LinkedBlockingQueue<>());
		test("ArrayBlockingQueue", new ArrayBlockingQueue<>(3));
		test("SynchronousQueue", new SynchronousQueue<>());
	}
}
